package QianFeng06.LambdaDemo;

import com.sun.javafx.tk.TKPulseListener;

import java.util.Arrays;
import java.util.Comparator;
import java.util.function.*;

/**
 * Lambda表达式
 * Lambda表达式(也称为闭包)是整个Java 8发行版中最受期待的在Java语言层面上的改变，Lambda允许把函数作为
 * 一个方法的参数(函数作为参数传递进方法中)，或者把代码看成数据。Lambda表达式用于简化AVA中接口
 * 式的匿名内部类。被称为函数式接口的概念。函数式接口就是一个具有一个方法的普通接口。像这样的接口,
 * 可以被隐式转换为lambda表达式。
 *
 * 默认方法与静态方法并影响函数式接口的契约，可以任意使用
 **/
public class LambdaDemo {
    public static void main(String[] args) {
        lambda();
        //三种写法
        IEat iEat1 = new IEatImpl();
        iEat1.eat();

        IEat iEat2 = new IEat() {
            @Override
            public void eat() {
                System.out.println("eat banana");
            }
        };
        iEat2.eat();

        /*lambda表达式*/
        //好处：1.代码简介 2.不会单独生成class文件
        //没有参数时使用
        IEat iEat3 = ()->{
            System.out.println("eat apple");
        };
        iEat3.eat();
        //有参数时使用，参数类型可以省略
        IEat1 iEat11 = (thing, name) -> System.out.println("eat:" + thing + ",name:" + name);
        iEat11.eat("orange","桔子");
        //带返回值的方法
        IEat2 iEat21 = thing -> 10;
        System.out.println("吃了" + iEat21.eat("orange") + "斤桔子");

        /*---------------------------------对Student类操作---------------------------------*/
        System.out.println("-----------------------对Student类操作-----------------------");
        Student[] students = {
                new Student("涛宝",1),
                new Student("大神",18),
                new Student("大侠",25)
        };
        Arrays.sort(students, new Comparator<Student>() {
            public int compare(Student o1, Student o2) {
                return o1.getAge() - o2.getAge();
            }
        });
        //lambda表达式
        //Comparator<Student> c = (o1, o2) -> o1.getAge() - o2.getAge();
        Arrays.sort(students, (o1, o2) -> o1.getAge() - o2.getAge());
        System.out.println(Arrays.toString(students));
    }
    //----------------------------------------------------------------------------------------------------------------
    /**
     * JDK1.8Lambda表达式
     * 在lambda表达式中，使用方法的引用，来传递方法方法的行为参数化
     * 方法的引用的语法，主要有三类
     * 1.指向静态方法的方法引用，例如Integer的parseInt方法 ，可以写成Integer::parseInt
     *      类：：静态方法名
     * 2.指向任意类型实例方法的方法引用，例如String的length方法，写成String::length；
     *     类：：实例方法名
     * 3.指向现有对象的实例方法的方法引用
     *     对象：：实例方法名
     * 构造器的引用：对于一个现有构造函数，你可以利用它的名称和关键字new来创建它的一个引用ClassName::new；
     **/
    private static void lambda() {
        /*--------------------方法的引用--------------------*/
        // 类：：静态方法名
        Comparator<Integer> bb = Integer::compare;
        System.out.println(bb.compare(3, 2));
        Comparator<Integer> cc = (x, y) -> Integer.compare(x, y);
        System.out.println(cc.compare(3, 2));

        Comparator<Integer> dd = (x, y) -> x.compareTo(y);
        System.out.println(dd.compare(3, 2));
        Comparator<Integer> ee = Integer::compareTo;
        System.out.println(ee.compare(3, 2));
        // 类：：实例方法名
        BiPredicate<String, String> bp = (x, y) -> x.equals(y);
        System.out.println(bp.test("a", "b"));
        BiPredicate<String, String> bp1 = String::equals;
        System.out.println(bp1.test("a", "b"));

        // 对象：：实例方法名
        Consumer<String> con1 = x -> System.out.println(x);
        con1.accept("abc");
        Consumer<String> con = System.out::println;
        con.accept("abc");

        Student student = new Student("上海", 18);
        Supplier<String> supper1 = () -> student.getName();
        System.out.println(supper1.get());
        Supplier<String> supper = student::getName;
        System.out.println(supper.get());

        /*--------------------构造器的引用--------------------*/
        // 无参构造函数，创建实例
        Supplier<Student> supper2 = () -> new Student();
        Supplier<Student> supper3 = Student::new;
        Student student1 = supper3.get();
        student1.setName("上海");
        // 一个参数
        Function<String, Student> fun = name -> new Student(name);
        Function<String, Student> fun1 = Student::new;
        System.out.println(fun1.apply("beijing"));
        // 两个参数
        BiFunction<String, Integer, Student> bFun = (name, age) -> new Student(name, age);
        BiFunction<String, Integer, Student> bFun1 = Student::new;
        System.out.println(bFun1.apply("小红", 18));

    }

}



//只有一个抽象方法的接口（无参）
interface IEat {
    void eat();
    //默认方法 不影响lambda表达式
    default void print1() {
        System.out.println("default method");
    }
    //静态方法 不影响lambda表达式
    static void print2() {
        System.out.println("static method");
    }
}

class IEatImpl implements IEat {

    @Override
    public void eat() {
        System.out.println("eat watermelon");
    }
}

//有参数
interface IEat1 {
    void eat(String thing, String name);
}

//有参数和返回值
interface IEat2 {
    int eat(String thing);
}
